#include "helper/sqlite/QueryResult.h"

#include <sqlite3.h>

#include "helper/sqlite/Error.h"

namespace helper {
namespace sqlite {

QueryResult::QueryResult(const std::error_code & ec, void * stmt)
: IResult(ec)
, _stmt((stmt))
{
}
QueryResult::~QueryResult(){
}


QueryResult::QueryResult(QueryResult && other)
: IResult(std::move(other))
{
  _stmt = other._stmt;
  other._stmt = nullptr;
}
QueryResult & QueryResult::operator= (QueryResult && other)
{
  IResult::operator=(std::move(other));

  _stmt = other._stmt;
  other._stmt = nullptr;

  return *this;
}

int QueryResult::fetchCode() const {
  switch(error::sqlite_error(_ec.value())){
    case error::sqlite_error::done: return  0;
    case error::sqlite_error::row : return  1;
    case error::sqlite_error::ok : return 1;
    default         : return -1;
  }
}

bool QueryResult::isOk() const{
  return fetchCode() > 0 && _stmt != nullptr;
}
void QueryResult::next(){
  if(_stmt != nullptr)
    errorCode().assign(sqlite3_step(static_cast<sqlite3_stmt*>(_stmt)), error::SqliteCategory());
  else{
    errorCode() = std::make_error_code(std::errc::invalid_argument);
  }
}

std::optional<Value> QueryResult::values(int index) const{
  if(_stmt != nullptr){
    if(index >= 0 && index < columnCount())
      return std::make_optional<Value>(_stmt, index);
    else 
      return std::nullopt;
  }

  const_cast<QueryResult*>(this)->errorCode() = std::make_error_code(std::errc::invalid_argument);
  return std::nullopt;
}

int QueryResult::columnCount() const{
  if(_stmt != nullptr) {
      return sqlite3_column_count(static_cast<sqlite3_stmt*>(_stmt));
  }
  const_cast<QueryResult*>(this)->errorCode() = std::make_error_code(std::errc::invalid_argument);
  return 0;
}

}//namespace sqlite
}//namespace helper
